package com.auxiliary;

import java.util.ArrayList;
import java.util.List;

import com.myidis.entity.DIResult;
import com.myidis.entity.TimeSequence;

public class DICalculator{
	/// <summary>
    /// 用于计算扩散指数的指标组合
    /// </summary>
	private ArrayList<TimeSequence> TimeSequenceSet;
	/// <summary>
	/// 指标中最短的序列长度
	/// </summary>
    private int seiesLength;
    /// <summary>
    /// 指标个数
    /// </summary>
    private int TimeSequenceCount;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="TimeSequenceSet">指标组合</param>
    public DICalculator(ArrayList<TimeSequence> TimeSequenceSet)
    {

        this.TimeSequenceSet = TimeSequenceSet;            
        //this.TimeSequenceCount = TimeSequenceSet==null?0:TimeSequenceSet.Count;
        //this.seiesLength = TimeSequenceSet==null?0:(TimeSequenceSet[0]==null?0:TimeSequenceSet[0].TimeSequence.getValues().Count);
    }
    
   /// <summary>
   /// 计算扩散指数
   /// </summary>
   /// <returns></returns>
    private ArrayList<Double> CalculateDI()
    { 
        ArrayList<Double> DIResult=new ArrayList<Double>();
        int interval = 3;  //两比较指标值的时间差,默认值为3个月
        
        for (int i = 0; i < interval; i++)
            DIResult.add(50.0);
        Double devia = 0.0001; //devia表示当一个指标变化幅度不超过该值时，认为指标值未发生显著变化,默认值设为1%
        for (int i = interval; i < seiesLength; i++)//对每一个时间点进行操作
        {
            Double tempDI = 0.0;
                for( TimeSequence TimeSequence : TimeSequenceSet)//对每一个指标进行操作
                {
                    ArrayList<Double> tt = TimeSequence.getValues();
                    ArrayList<Double> temp = new ArrayList<Double>();
                    for (Double d : tt)
                        temp.add(d);
                    if (temp.get(i) > (1 + devia) * temp.get(i - interval))
                    {
                        tempDI = tempDI + 1; // 当指标值显著上升时，值加1
                    }

                    else if (temp.get(i) > (1 - devia) * temp.get(i - interval))
                    {
                       tempDI = tempDI + 0.5;  //当指标值未发生显著变化时，值加0.5
                    }

                    // 当指标值显著下降时，值不变

                }
            DIResult.add(tempDI/TimeSequenceCount*100);
        }              
                   
        return DIResult;
    }

    /// <summary>
    /// 计算移动平均后的扩散指数
    /// </summary>
    /// <param name="DI">扩散指数</param>
    /// <returns></returns>
    private List<Double> CalculateMovingDI(List<Double> DI)
    {
        if (DI == null) return null;
        List<Double> MDIResult = new ArrayList<Double>();
        BasicCalculator basicCal = new BasicCalculator();
      
        List<Double> weightArrayList = new ArrayList<Double>();
        Double temp = -3.0 / 35.0;
        weightArrayList.add(temp);
        temp = 12.0 / 35.0;
        weightArrayList.add(temp);
        temp = 17.0 / 35.0;
        weightArrayList.add(temp);
        temp = 12.0 / 35.0;
        weightArrayList.add(temp);
        temp = -3.0 / 35.0;
        weightArrayList.add(temp);
        MDIResult=basicCal.MAverWithWeight(5, DI,weightArrayList);           
        return MDIResult;
    }
    /// <summary>
    /// 计算计算移动平均后的扩散指数的累积扩散指数
    /// </summary>
    /// <param name="movingDI"></param>
    /// <returns></returns>
    private List<Double> CalculateCumDI(List<Double> movingDI)
    {
        if (movingDI == null) return null;
        List<Double> CDIResult = new ArrayList<Double>();
        CDIResult.add(50.0);            
        for (int i=1;i<movingDI.size();i++)
        {
            CDIResult.add(CDIResult.get(i-1)+movingDI.get(i-1)-50);
        }
        return CDIResult;
    }

    /// <summary>
    ///计算扩散指数
    /// DI是未经平滑的扩散指数，称为扩散指数
    /// movingDI是DI移动平均后的扩散指数，目前采用的是9项移动平均
    /// commulativeDI是movingDI的累计:commulativeDI=cummulativeDI(-1)+movingDI-50;
    /// </summary>
    /// <returns></returns>
    public DIResult Calculate()
    {
        if (TimeSequenceSet == null) return null;
        this.TimeSequenceCount = TimeSequenceSet.size();
        for (TimeSequence timeSequence : TimeSequenceSet)
            if (timeSequence == null) return null;
            else if (timeSequence.getValues() == null) return null;
        this.seiesLength = TimeSequenceSet.get(0).getValues().size();
        for (TimeSequence timeSequence : TimeSequenceSet)
            if (timeSequence.getValues().size()< this.seiesLength) this.seiesLength = timeSequence.getValues().size();
        
        DIResult dIResult = new DIResult();
        dIResult.setdI(this.CalculateDI());
        BasicCalculator cal = new BasicCalculator();
        dIResult.setMovingDI(cal.movingAvg(9, dIResult.getdI()));
        //dIResult.MovingDI = this.CalculateMovingDI(dIResult.HistoricalDI);
        //dIResult.MovingDI = this.CalculateMovingDI(dIResult.MovingDI);
        //dIResult.MovingDI = this.CalculateMovingDI(dIResult.MovingDI);

        dIResult.setCummunativeDI(this.CalculateCumDI(dIResult.getMovingDI()));
        return dIResult;         
        

    }

    
}
